Based on responses to surveys designed to gauge parent, student, and teacher perceptions of the quality of New York City schools, we’ll going to investigate the following questions:

The next two files, masterfile11_gened_final.xlsx and masterfile11_gened_final.txt, contain survey data for “general education” schools — those that do not specifically serve populations with special needs.

The files masterfile11_d75_final.xlsx and masterfile11_d75_final.txt contain survey data for District 75 schools, which provide special education support for children with special needs such as learning or physical disabilities.

you can download these files from: https://data.cityofnewyork.us/Education/2011-NYC-School-Survey/mnz3-dyi8

We’re going to use the combined data set that have the demographic data: “combined.csv” you can download the file from: https://data.world/dataquest/nyc-schools-data/workspace/file?filename=combined.csv

1. Load the packages we ’ll goint to use:

library(readr)
library(dplyr)
replacing previous import by ‘rlang::dots_n’ when loading ‘dplyr’
Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(stringr)
library(purrr)
library(tidyr)
library(ggplot2)

2. Read the csv and tsv files:

combined <- read_csv("/home/matias/Documents/repos/Data-Science-Notebooks/NYC Schools Perceptions/combined.csv")
Parsed with column specification:
cols(
  .default = col_double(),
  DBN = col_character(),
  school_name = col_character(),
  boro = col_character()
)
See spec(...) for full column specifications.
survey <- read_tsv("/home/matias/Documents/repos/Data-Science-Notebooks/NYC Schools Perceptions/2011 data files online/masterfile11_gened_final.txt")
Parsed with column specification:
cols(
  .default = col_double(),
  dbn = col_character(),
  bn = col_character(),
  schoolname = col_character(),
  studentssurveyed = col_character(),
  schooltype = col_character(),
  p_q1 = col_logical(),
  p_q3d = col_logical(),
  p_q9 = col_logical(),
  p_q10 = col_logical(),
  p_q12aa = col_logical(),
  p_q12ab = col_logical(),
  p_q12ac = col_logical(),
  p_q12ad = col_logical(),
  p_q12ba = col_logical(),
  p_q12bb = col_logical(),
  p_q12bc = col_logical(),
  p_q12bd = col_logical(),
  t_q6m = col_logical(),
  t_q9 = col_logical(),
  t_q10a = col_logical()
  # ... with 18 more columns
)
See spec(...) for full column specifications.
survey_d75 <- read_tsv("/home/matias/Documents/repos/Data-Science-Notebooks/NYC Schools Perceptions/2011 data files online/masterfile11_d75_final.txt")
Parsed with column specification:
cols(
  .default = col_double(),
  dbn = col_character(),
  bn = col_character(),
  schoolname = col_character(),
  studentssurveyed = col_character(),
  schooltype = col_character(),
  p_q5 = col_logical(),
  p_q9 = col_logical(),
  p_q13a = col_logical(),
  p_q13b = col_logical(),
  p_q13c = col_logical(),
  p_q13d = col_logical(),
  p_q14a = col_logical(),
  p_q14b = col_logical(),
  p_q14c = col_logical(),
  p_q14d = col_logical(),
  t_q11a = col_logical(),
  t_q11b = col_logical(),
  t_q14 = col_logical(),
  t_q15a = col_logical(),
  t_q15b = col_logical()
  # ... with 14 more columns
)
See spec(...) for full column specifications.
combined
survey
survey_d75

Simplifying the survey data frames to include only variables we will need for our analysis:

combined_up <-combined %>%
  select(1, 3:7, 13, 15, 19:22, 27:30)
  
  
survey_up <- survey %>%
  filter((schooltype == "High School") | (schooltype == "Middle / High School")) %>%
  select(1, 17:32)
  
survey_d75_up <- survey_d75 %>%
  select(1, 17:32)
  
combined_up
survey_up
survey_d75_up

Combining survey data frames first:

We can use dplyr bind_rows() to combine data frames with differents number of columns, but because both data frames have the same number of it, we can use simple rbind.

combined_surveys <- rbind(survey_up, survey_d75_up)
combined_up <- combined_up %>%
  rename(dbn = `DBN`)

Joining combined survey data frame with combined_up data frame (demographic data):

combined_final <- combined_up %>%
  left_join(combined_surveys, by = "dbn")
combined_final <- combined_final %>%
  mutate(quality_metrics = (`saf_tot_11`+`com_tot_11`+`eng_tot_11`+`aca_tot_11`)/4)

Subsetting the correlation matrix:

cor_tib <- cor_mat %>%
  as_tibble(rownames = "variable")
 
saf_tot_11_cors <- cor_tib %>%
  filter((variable == "avg_sat_score") | (variable == "asian_per") | (variable == "white_per") | (variable == "black_per") | (variable == "hispanic_per") | (variable == "lat") | (variable == "long") | (variable == "dropout_percent")) %>%
  select(variable, saf_tot_11) %>%
  filter(saf_tot_11 > 0.15 | saf_tot_11 < -0.15)
com_tot_11_cors <- cor_tib %>%
  filter((variable == "avg_sat_score") | (variable == "asian_per") | (variable == "white_per") | (variable == "black_per") | (variable == "hispanic_per") | (variable == "lat") | (variable == "long") | (variable == "dropout_percent")) %>%
  select(variable, com_tot_11) %>%
  filter(com_tot_11 > 0.15 | com_tot_11 < -0.15)
eng_tot_11_cors <- cor_tib %>%
  filter((variable == "avg_sat_score") | (variable == "asian_per") | (variable == "white_per") | (variable == "black_per") | (variable == "hispanic_per") | (variable == "lat") | (variable == "long") | (variable == "dropout_percent")) %>%
  select(variable, eng_tot_11) %>%
  filter(eng_tot_11 > 0.15 | eng_tot_11 < -0.15)
aca_tot_11_cors <- cor_tib %>%
  filter((variable == "avg_sat_score") | (variable == "asian_per") | (variable == "white_per") | (variable == "black_per") | (variable == "hispanic_per") | (variable == "lat") | (variable == "long") | (variable == "dropout_percent")) %>%
  select(variable, aca_tot_11) %>%
  filter(aca_tot_11 > 0.15 | aca_tot_11 < -0.15)
quality_metrics_cors <- cor_tib %>%
  filter((variable == "avg_sat_score") | (variable == "asian_per") | (variable == "white_per") | (variable == "black_per") | (variable == "hispanic_per") | (variable == "lat") | (variable == "long") | (variable == "dropout_percent")) %>%
  select(variable, quality_metrics) %>%
  filter(quality_metrics > 0.15 | quality_metrics < -0.15)

Scatter plots with the variables filtered:

A group for scatter plots for each survey variable: saf_tot_11, com_tot_11, eng_tot_11, aca_tot_11, quality_metrics (avg of saf, com, eng, aca).

First: “Quality metrics vs Demographic Variables” - colour: Deepskyblue

create_scatter <- function(x,y) {
  ggplot(data = combined_final) + 
     aes_string(x = x, y = y) +  
     geom_point(na.rm=TRUE, alpha = 0.3, colour="deepskyblue") + 
     labs(title = "Quality metrics vs Demographic Variables") + 
     theme(panel.background = element_rect(fill = "white"), plot.title = element_text(hjust = 0.5))
}
x_var <- names(combined_final)[33]
y_var <- names(combined_final)[c(6,9:13)]
map2(x_var, y_var, create_scatter)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Second: “Safety and Respect vs Demographic Variables” - colour: darkorange

create_scatter2 <- function(x,y) {
  ggplot(data = combined_final) + 
     aes_string(x = x, y = y) +  
     geom_point(na.rm=TRUE, alpha = 0.3, colour="darkorange") + 
     labs(title = "Safety and Respect vs Demographic Variables") + 
     theme(panel.background = element_rect(fill = "white"), plot.title = element_text(hjust = 0.5))
}
x_var <- names(combined_final)[29]
y_var <- names(combined_final)[c(6,9:13)]
map2(x_var, y_var, create_scatter2)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Third: “Communication vs Demographic Variables” - colour: green2

create_scatter3 <- function(x,y) {
  ggplot(data = combined_final) + 
     aes_string(x = x, y = y) +  
     geom_point(na.rm=TRUE, alpha = 0.3, colour="green2") + 
     labs(title = "Communication vs Demographic Variables") + 
     theme(panel.background = element_rect(fill = "white"), plot.title = element_text(hjust = 0.5))
}
x_var <- names(combined_final)[30]
y_var <- names(combined_final)[c(6,9:13)]
map2(x_var, y_var, create_scatter3)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Fourth: “Engagement vs Demographic Variables” - colour: blueviolet

create_scatter4 <- function(x,y) {
  ggplot(data = combined_final) + 
     aes_string(x = x, y = y) +  
     geom_point(na.rm=TRUE, alpha = 0.3, colour="blueviolet") + 
     labs(title = "Engagement vs Demographic Variables") + 
     theme(panel.background = element_rect(fill = "white"), plot.title = element_text(hjust = 0.5))
}
x_var <- names(combined_final)[31]
y_var <- names(combined_final)[c(6,9:13)]
map2(x_var, y_var, create_scatter4)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

Fourth: “Academic Expectations vs Demographic Variables” - colour: firebrick1

create_scatter5 <- function(x,y) {
  ggplot(data = combined_final) + 
     aes_string(x = x, y = y) +  
     geom_point(na.rm=TRUE, alpha = 0.3, colour="firebrick1") + 
     labs(title = "Academic Expectations vs Demographic Variables") + 
     theme(panel.background = element_rect(fill = "white"), plot.title = element_text(hjust = 0.5))
}
x_var <- names(combined_final)[32]
y_var <- names(combined_final)[c(6,9:13)]
map2(x_var, y_var, create_scatter5)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

It would be interesting to see whether parents, students, and teachers have similar perceptions about the four school quality metrics they were surveyed about:

Safety and Respect
Communication
Engagement
Academic Expectations

We can group the data by question and survey response type (parent, student, teacher, or total) and then calculate a summary average for each group.

combined_survey_gather <- combined_final %>%
  gather(key = "survey_question", value = "score", 17:28,33) %>%
  mutate(response_type = str_split(`survey_question`, "_", simplify = TRUE)[,2], metric = str_split(`survey_question`, "_", simplify = TRUE)[,1]) 
  
combined_survey_gather <- combined_survey_gather %>%
  mutate(response_type = if_else(response_type == "p", "parent", if_else(response_type == "t", "teacher", if_else(response_type == "s", "student", "stp_combined"))))
  

Now its time to group the data into categories: Students, Teachers and Parents.

1. Summary perceptions:

perceptions <- combined_survey_gather %>%
  group_by(response_type, metric) %>%
  summarize(avg_score = mean(score, na.rm = TRUE))
perceptions
combined_survey_gather <- combined_survey_gather %>%
  drop_na(score)
combined_survey_gather %>%
 # filter(response_type != "quality") %>%
  ggplot() +
  aes(x = survey_question, y = score, fill = response_type) +
  geom_boxplot() + 
  labs(title = "Perceptions of quality education in NYC High Schools") + 
  theme(panel.background = element_rect(fill = "white"), plot.title = element_text(hjust = 0.5), axis.text.x=element_text(angle=90, hjust=1, size=8), panel.spacing.x=unit(0.5, "lines"))  

There are still interesting questions we can answer:

LS0tCnRpdGxlOiAiTllDIFNjaG9vbHMgUGVyY2VwdGlvbnMiCmF1dGhvcjogIk1hdGlhcyBMLiBDb25kZSIKZGF0YTogY29tYmluZWQuY3N2LCBtYXN0ZXJmaWxlMTFfZ2VuZWRfZmluYWwudHh0LCBtYXN0ZXJmaWxlMTFfZDc1X2ZpbmFsLnR4dApvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpCYXNlZCBvbiByZXNwb25zZXMgdG8gc3VydmV5cyBkZXNpZ25lZCB0byBnYXVnZSBwYXJlbnQsIHN0dWRlbnQsIGFuZCB0ZWFjaGVyIHBlcmNlcHRpb25zIG9mIHRoZSBxdWFsaXR5IG9mIE5ldyBZb3JrIENpdHkgc2Nob29scywgd2UnbGwgZ29pbmcgdG8gaW52ZXN0aWdhdGUgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnM6IAoKLSBEbyBzdHVkZW50LCB0ZWFjaGVyLCBhbmQgcGFyZW50IHBlcmNlcHRpb25zIG9mIE5ZQyBzY2hvb2wgcXVhbGl0eSBhcHBlYXIgdG8gYmUgcmVsYXRlZCB0byBkZW1vZ3JhcGhpYyBhbmQgYWNhZGVtaWMgc3VjY2VzcyBtZXRyaWNzPwoKLSBEbyBzdHVkZW50cywgdGVhY2hlcnMsIGFuZCBwYXJlbnRzIGhhdmUgc2ltaWxhciBwZXJjZXB0aW9ucyBvZiBOWUMgc2Nob29sIHF1YWxpdHk/CgpUaGUgbmV4dCB0d28gZmlsZXMsIG1hc3RlcmZpbGUxMV9nZW5lZF9maW5hbC54bHN4IGFuZCBtYXN0ZXJmaWxlMTFfZ2VuZWRfZmluYWwudHh0LCBjb250YWluIHN1cnZleSBkYXRhIGZvciAiZ2VuZXJhbCBlZHVjYXRpb24iIHNjaG9vbHMg4oCUIHRob3NlIHRoYXQgZG8gbm90IHNwZWNpZmljYWxseSBzZXJ2ZSBwb3B1bGF0aW9ucyB3aXRoIHNwZWNpYWwgbmVlZHMuCgpUaGUgZmlsZXMgbWFzdGVyZmlsZTExX2Q3NV9maW5hbC54bHN4IGFuZCBtYXN0ZXJmaWxlMTFfZDc1X2ZpbmFsLnR4dCBjb250YWluIHN1cnZleSBkYXRhIGZvciBEaXN0cmljdCA3NSBzY2hvb2xzLCB3aGljaCBwcm92aWRlIHNwZWNpYWwgZWR1Y2F0aW9uIHN1cHBvcnQgZm9yIGNoaWxkcmVuIHdpdGggc3BlY2lhbCBuZWVkcyBzdWNoIGFzIGxlYXJuaW5nIG9yIHBoeXNpY2FsIGRpc2FiaWxpdGllcy4gCgp5b3UgY2FuIGRvd25sb2FkIHRoZXNlIGZpbGVzIGZyb206Cmh0dHBzOi8vZGF0YS5jaXR5b2ZuZXd5b3JrLnVzL0VkdWNhdGlvbi8yMDExLU5ZQy1TY2hvb2wtU3VydmV5L21uejMtZHlpOAoKCldlJ3JlIGdvaW5nIHRvIHVzZSB0aGUgY29tYmluZWQgZGF0YSBzZXQgdGhhdCBoYXZlIHRoZSBkZW1vZ3JhcGhpYyBkYXRhOiAiY29tYmluZWQuY3N2Igp5b3UgY2FuIGRvd25sb2FkIHRoZSBmaWxlIGZyb206IGh0dHBzOi8vZGF0YS53b3JsZC9kYXRhcXVlc3QvbnljLXNjaG9vbHMtZGF0YS93b3Jrc3BhY2UvZmlsZT9maWxlbmFtZT1jb21iaW5lZC5jc3YKCgojIyMjIDEuIExvYWQgdGhlIHBhY2thZ2VzIHdlICdsbCBnb2ludCB0byB1c2U6CmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKYGBgCiMjIyMgMi4gUmVhZCB0aGUgY3N2IGFuZCB0c3YgZmlsZXM6IApgYGB7cn0KY29tYmluZWQgPC0gcmVhZF9jc3YoIi9ob21lL21hdGlhcy9Eb2N1bWVudHMvcmVwb3MvRGF0YS1TY2llbmNlLU5vdGVib29rcy9OWUMgU2Nob29scyBQZXJjZXB0aW9ucy9jb21iaW5lZC5jc3YiKQpzdXJ2ZXkgPC0gcmVhZF90c3YoIi9ob21lL21hdGlhcy9Eb2N1bWVudHMvcmVwb3MvRGF0YS1TY2llbmNlLU5vdGVib29rcy9OWUMgU2Nob29scyBQZXJjZXB0aW9ucy8yMDExIGRhdGEgZmlsZXMgb25saW5lL21hc3RlcmZpbGUxMV9nZW5lZF9maW5hbC50eHQiKQpzdXJ2ZXlfZDc1IDwtIHJlYWRfdHN2KCIvaG9tZS9tYXRpYXMvRG9jdW1lbnRzL3JlcG9zL0RhdGEtU2NpZW5jZS1Ob3RlYm9va3MvTllDIFNjaG9vbHMgUGVyY2VwdGlvbnMvMjAxMSBkYXRhIGZpbGVzIG9ubGluZS9tYXN0ZXJmaWxlMTFfZDc1X2ZpbmFsLnR4dCIpCmBgYApgYGB7cn0KY29tYmluZWQKc3VydmV5CnN1cnZleV9kNzUKYGBgCiMjIyMgU2ltcGxpZnlpbmcgdGhlIHN1cnZleSBkYXRhIGZyYW1lcyB0byBpbmNsdWRlIG9ubHkgdmFyaWFibGVzIHdlIHdpbGwgbmVlZCBmb3Igb3VyIGFuYWx5c2lzOgpgYGB7cn0KY29tYmluZWRfdXAgPC1jb21iaW5lZCAlPiUKICBzZWxlY3QoMSwgMzo3LCAxMywgMTUsIDE5OjIyLCAyNzozMCkKICAKICAKc3VydmV5X3VwIDwtIHN1cnZleSAlPiUKICBmaWx0ZXIoKHNjaG9vbHR5cGUgPT0gIkhpZ2ggU2Nob29sIikgfCAoc2Nob29sdHlwZSA9PSAiTWlkZGxlIC8gSGlnaCBTY2hvb2wiKSkgJT4lCiAgc2VsZWN0KDEsIDE3OjMyKQogIApzdXJ2ZXlfZDc1X3VwIDwtIHN1cnZleV9kNzUgJT4lCiAgc2VsZWN0KDEsIDE3OjMyKQogIApjb21iaW5lZF91cApzdXJ2ZXlfdXAKc3VydmV5X2Q3NV91cApgYGAKIyMjIyBDb21iaW5pbmcgc3VydmV5IGRhdGEgZnJhbWVzIGZpcnN0OgpXZSBjYW4gdXNlIGRwbHlyIGJpbmRfcm93cygpIHRvIGNvbWJpbmUgZGF0YSBmcmFtZXMgd2l0aCBkaWZmZXJlbnRzIG51bWJlciBvZiBjb2x1bW5zLCAKYnV0IGJlY2F1c2UgYm90aCBkYXRhIGZyYW1lcyBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBpdCwgd2UgY2FuIHVzZSBzaW1wbGUgcmJpbmQuCmBgYHtyfQpjb21iaW5lZF9zdXJ2ZXlzIDwtIHJiaW5kKHN1cnZleV91cCwgc3VydmV5X2Q3NV91cCkKY29tYmluZWRfdXAgPC0gY29tYmluZWRfdXAgJT4lCiAgcmVuYW1lKGRibiA9IGBEQk5gKQpgYGAKIyMjIyBKb2luaW5nIGNvbWJpbmVkIHN1cnZleSBkYXRhIGZyYW1lIHdpdGggY29tYmluZWRfdXAgZGF0YSBmcmFtZSAoZGVtb2dyYXBoaWMgZGF0YSk6CmBgYHtyfQpjb21iaW5lZF9maW5hbCA8LSBjb21iaW5lZF91cCAlPiUKICBsZWZ0X2pvaW4oY29tYmluZWRfc3VydmV5cywgYnkgPSAiZGJuIikKCmNvbWJpbmVkX2ZpbmFsIDwtIGNvbWJpbmVkX2ZpbmFsICU+JQogIG11dGF0ZShxdWFsaXR5X21ldHJpY3MgPSAoYHNhZl90b3RfMTFgK2Bjb21fdG90XzExYCtgZW5nX3RvdF8xMWArYGFjYV90b3RfMTFgKS80KQpgYGAKIyMjIyBMZXQncyBnZXQgYW4gaWRlYSBvZiB3aGljaCBkZW1vZ3JhcGhpYyBhbmQgdGVzdCBzY29yZSB2YXJpYWJsZXMgbWF5IGJlIHJlbGF0ZWQgdG8gcGFyZW50IHdpdGggYSBjb3JyZWxhdGlvbiBtYXRyaXg6CmBgYHtyfQpjb3JfbWF0IDwtIGNvbWJpbmVkX2ZpbmFsICU+JQogIHNlbGVjdF9pZihpcy5udW1lcmljKSAlPiUgCiAgY29yKHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQpgYGAKIyMjIyBTdWJzZXR0aW5nIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXg6CmBgYHtyfQpjb3JfdGliIDwtIGNvcl9tYXQgJT4lCiAgYXNfdGliYmxlKHJvd25hbWVzID0gInZhcmlhYmxlIikKIApzYWZfdG90XzExX2NvcnMgPC0gY29yX3RpYiAlPiUKICBmaWx0ZXIoKHZhcmlhYmxlID09ICJhdmdfc2F0X3Njb3JlIikgfCAodmFyaWFibGUgPT0gImFzaWFuX3BlciIpIHwgKHZhcmlhYmxlID09ICJ3aGl0ZV9wZXIiKSB8ICh2YXJpYWJsZSA9PSAiYmxhY2tfcGVyIikgfCAodmFyaWFibGUgPT0gImhpc3BhbmljX3BlciIpIHwgKHZhcmlhYmxlID09ICJsYXQiKSB8ICh2YXJpYWJsZSA9PSAibG9uZyIpIHwgKHZhcmlhYmxlID09ICJkcm9wb3V0X3BlcmNlbnQiKSkgJT4lCiAgc2VsZWN0KHZhcmlhYmxlLCBzYWZfdG90XzExKSAlPiUKICBmaWx0ZXIoc2FmX3RvdF8xMSA+IDAuMTUgfCBzYWZfdG90XzExIDwgLTAuMTUpCgpjb21fdG90XzExX2NvcnMgPC0gY29yX3RpYiAlPiUKICBmaWx0ZXIoKHZhcmlhYmxlID09ICJhdmdfc2F0X3Njb3JlIikgfCAodmFyaWFibGUgPT0gImFzaWFuX3BlciIpIHwgKHZhcmlhYmxlID09ICJ3aGl0ZV9wZXIiKSB8ICh2YXJpYWJsZSA9PSAiYmxhY2tfcGVyIikgfCAodmFyaWFibGUgPT0gImhpc3BhbmljX3BlciIpIHwgKHZhcmlhYmxlID09ICJsYXQiKSB8ICh2YXJpYWJsZSA9PSAibG9uZyIpIHwgKHZhcmlhYmxlID09ICJkcm9wb3V0X3BlcmNlbnQiKSkgJT4lCiAgc2VsZWN0KHZhcmlhYmxlLCBjb21fdG90XzExKSAlPiUKICBmaWx0ZXIoY29tX3RvdF8xMSA+IDAuMTUgfCBjb21fdG90XzExIDwgLTAuMTUpCgplbmdfdG90XzExX2NvcnMgPC0gY29yX3RpYiAlPiUKICBmaWx0ZXIoKHZhcmlhYmxlID09ICJhdmdfc2F0X3Njb3JlIikgfCAodmFyaWFibGUgPT0gImFzaWFuX3BlciIpIHwgKHZhcmlhYmxlID09ICJ3aGl0ZV9wZXIiKSB8ICh2YXJpYWJsZSA9PSAiYmxhY2tfcGVyIikgfCAodmFyaWFibGUgPT0gImhpc3BhbmljX3BlciIpIHwgKHZhcmlhYmxlID09ICJsYXQiKSB8ICh2YXJpYWJsZSA9PSAibG9uZyIpIHwgKHZhcmlhYmxlID09ICJkcm9wb3V0X3BlcmNlbnQiKSkgJT4lCiAgc2VsZWN0KHZhcmlhYmxlLCBlbmdfdG90XzExKSAlPiUKICBmaWx0ZXIoZW5nX3RvdF8xMSA+IDAuMTUgfCBlbmdfdG90XzExIDwgLTAuMTUpCgphY2FfdG90XzExX2NvcnMgPC0gY29yX3RpYiAlPiUKICBmaWx0ZXIoKHZhcmlhYmxlID09ICJhdmdfc2F0X3Njb3JlIikgfCAodmFyaWFibGUgPT0gImFzaWFuX3BlciIpIHwgKHZhcmlhYmxlID09ICJ3aGl0ZV9wZXIiKSB8ICh2YXJpYWJsZSA9PSAiYmxhY2tfcGVyIikgfCAodmFyaWFibGUgPT0gImhpc3BhbmljX3BlciIpIHwgKHZhcmlhYmxlID09ICJsYXQiKSB8ICh2YXJpYWJsZSA9PSAibG9uZyIpIHwgKHZhcmlhYmxlID09ICJkcm9wb3V0X3BlcmNlbnQiKSkgJT4lCiAgc2VsZWN0KHZhcmlhYmxlLCBhY2FfdG90XzExKSAlPiUKICBmaWx0ZXIoYWNhX3RvdF8xMSA+IDAuMTUgfCBhY2FfdG90XzExIDwgLTAuMTUpCgpxdWFsaXR5X21ldHJpY3NfY29ycyA8LSBjb3JfdGliICU+JQogIGZpbHRlcigodmFyaWFibGUgPT0gImF2Z19zYXRfc2NvcmUiKSB8ICh2YXJpYWJsZSA9PSAiYXNpYW5fcGVyIikgfCAodmFyaWFibGUgPT0gIndoaXRlX3BlciIpIHwgKHZhcmlhYmxlID09ICJibGFja19wZXIiKSB8ICh2YXJpYWJsZSA9PSAiaGlzcGFuaWNfcGVyIikgfCAodmFyaWFibGUgPT0gImxhdCIpIHwgKHZhcmlhYmxlID09ICJsb25nIikgfCAodmFyaWFibGUgPT0gImRyb3BvdXRfcGVyY2VudCIpKSAlPiUKICBzZWxlY3QodmFyaWFibGUsIHF1YWxpdHlfbWV0cmljcykgJT4lCiAgZmlsdGVyKHF1YWxpdHlfbWV0cmljcyA+IDAuMTUgfCBxdWFsaXR5X21ldHJpY3MgPCAtMC4xNSkKCmBgYAojIyMjIFNjYXR0ZXIgcGxvdHMgd2l0aCB0aGUgdmFyaWFibGVzIGZpbHRlcmVkOgoKQSBncm91cCBmb3Igc2NhdHRlciBwbG90cyBmb3IgZWFjaCBzdXJ2ZXkgdmFyaWFibGU6IHNhZl90b3RfMTEsIGNvbV90b3RfMTEsIGVuZ190b3RfMTEsIGFjYV90b3RfMTEsIHF1YWxpdHlfbWV0cmljcyAoYXZnIG9mIHNhZiwgY29tLCBlbmcsIGFjYSkuCgpGaXJzdDogIlF1YWxpdHkgbWV0cmljcyB2cyBEZW1vZ3JhcGhpYyBWYXJpYWJsZXMiIC0gY29sb3VyOiBEZWVwc2t5Ymx1ZSAKYGBge3J9CmNyZWF0ZV9zY2F0dGVyIDwtIGZ1bmN0aW9uKHgseSkgewogIGdncGxvdChkYXRhID0gY29tYmluZWRfZmluYWwpICsgCiAgICAgYWVzX3N0cmluZyh4ID0geCwgeSA9IHkpICsgIAogICAgIGdlb21fcG9pbnQobmEucm09VFJVRSwgYWxwaGEgPSAwLjMsIGNvbG91cj0iZGVlcHNreWJsdWUiKSArIAogICAgIGxhYnModGl0bGUgPSAiUXVhbGl0eSBtZXRyaWNzIHZzIERlbW9ncmFwaGljIFZhcmlhYmxlcyIpICsgCiAgICAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQp9Cgp4X3ZhciA8LSBuYW1lcyhjb21iaW5lZF9maW5hbClbMzNdCnlfdmFyIDwtIG5hbWVzKGNvbWJpbmVkX2ZpbmFsKVtjKDYsOToxMyldCgptYXAyKHhfdmFyLCB5X3ZhciwgY3JlYXRlX3NjYXR0ZXIpCgpgYGAKCgpTZWNvbmQ6ICJTYWZldHkgYW5kIFJlc3BlY3QgdnMgRGVtb2dyYXBoaWMgVmFyaWFibGVzIiAtIGNvbG91cjogZGFya29yYW5nZSAKCmBgYHtyfQpjcmVhdGVfc2NhdHRlcjIgPC0gZnVuY3Rpb24oeCx5KSB7CiAgZ2dwbG90KGRhdGEgPSBjb21iaW5lZF9maW5hbCkgKyAKICAgICBhZXNfc3RyaW5nKHggPSB4LCB5ID0geSkgKyAgCiAgICAgZ2VvbV9wb2ludChuYS5ybT1UUlVFLCBhbHBoYSA9IDAuMywgY29sb3VyPSJkYXJrb3JhbmdlIikgKyAKICAgICBsYWJzKHRpdGxlID0gIlNhZmV0eSBhbmQgUmVzcGVjdCB2cyBEZW1vZ3JhcGhpYyBWYXJpYWJsZXMiKSArIAogICAgIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKfQoKeF92YXIgPC0gbmFtZXMoY29tYmluZWRfZmluYWwpWzI5XQp5X3ZhciA8LSBuYW1lcyhjb21iaW5lZF9maW5hbClbYyg2LDk6MTMpXQoKbWFwMih4X3ZhciwgeV92YXIsIGNyZWF0ZV9zY2F0dGVyMikKCmBgYApUaGlyZDogIkNvbW11bmljYXRpb24gdnMgRGVtb2dyYXBoaWMgVmFyaWFibGVzIiAtIGNvbG91cjogZ3JlZW4yIAoKYGBge3J9CmNyZWF0ZV9zY2F0dGVyMyA8LSBmdW5jdGlvbih4LHkpIHsKICBnZ3Bsb3QoZGF0YSA9IGNvbWJpbmVkX2ZpbmFsKSArIAogICAgIGFlc19zdHJpbmcoeCA9IHgsIHkgPSB5KSArICAKICAgICBnZW9tX3BvaW50KG5hLnJtPVRSVUUsIGFscGhhID0gMC4zLCBjb2xvdXI9ImdyZWVuMiIpICsgCiAgICAgbGFicyh0aXRsZSA9ICJDb21tdW5pY2F0aW9uIHZzIERlbW9ncmFwaGljIFZhcmlhYmxlcyIpICsgCiAgICAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQp9Cgp4X3ZhciA8LSBuYW1lcyhjb21iaW5lZF9maW5hbClbMzBdCnlfdmFyIDwtIG5hbWVzKGNvbWJpbmVkX2ZpbmFsKVtjKDYsOToxMyldCgptYXAyKHhfdmFyLCB5X3ZhciwgY3JlYXRlX3NjYXR0ZXIzKQpgYGAKRm91cnRoOiAiRW5nYWdlbWVudCB2cyBEZW1vZ3JhcGhpYyBWYXJpYWJsZXMiIC0gY29sb3VyOiBibHVldmlvbGV0IAoKYGBge3J9CmNyZWF0ZV9zY2F0dGVyNCA8LSBmdW5jdGlvbih4LHkpIHsKICBnZ3Bsb3QoZGF0YSA9IGNvbWJpbmVkX2ZpbmFsKSArIAogICAgIGFlc19zdHJpbmcoeCA9IHgsIHkgPSB5KSArICAKICAgICBnZW9tX3BvaW50KG5hLnJtPVRSVUUsIGFscGhhID0gMC4zLCBjb2xvdXI9ImJsdWV2aW9sZXQiKSArIAogICAgIGxhYnModGl0bGUgPSAiRW5nYWdlbWVudCB2cyBEZW1vZ3JhcGhpYyBWYXJpYWJsZXMiKSArIAogICAgIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKfQoKeF92YXIgPC0gbmFtZXMoY29tYmluZWRfZmluYWwpWzMxXQp5X3ZhciA8LSBuYW1lcyhjb21iaW5lZF9maW5hbClbYyg2LDk6MTMpXQoKbWFwMih4X3ZhciwgeV92YXIsIGNyZWF0ZV9zY2F0dGVyNCkKCgpgYGAKRm91cnRoOiAiQWNhZGVtaWMgRXhwZWN0YXRpb25zIHZzIERlbW9ncmFwaGljIFZhcmlhYmxlcyIgLSBjb2xvdXI6IGZpcmVicmljazEgCgpgYGB7cn0KY3JlYXRlX3NjYXR0ZXI1IDwtIGZ1bmN0aW9uKHgseSkgewogIGdncGxvdChkYXRhID0gY29tYmluZWRfZmluYWwpICsgCiAgICAgYWVzX3N0cmluZyh4ID0geCwgeSA9IHkpICsgIAogICAgIGdlb21fcG9pbnQobmEucm09VFJVRSwgYWxwaGEgPSAwLjMsIGNvbG91cj0iZmlyZWJyaWNrMSIpICsgCiAgICAgbGFicyh0aXRsZSA9ICJBY2FkZW1pYyBFeHBlY3RhdGlvbnMgdnMgRGVtb2dyYXBoaWMgVmFyaWFibGVzIikgKyAKICAgICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSwgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCn0KCnhfdmFyIDwtIG5hbWVzKGNvbWJpbmVkX2ZpbmFsKVszMl0KeV92YXIgPC0gbmFtZXMoY29tYmluZWRfZmluYWwpW2MoNiw5OjEzKV0KCm1hcDIoeF92YXIsIHlfdmFyLCBjcmVhdGVfc2NhdHRlcjUpCmBgYAojIyMjIEl0IHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIHNlZSB3aGV0aGVyIHBhcmVudHMsIHN0dWRlbnRzLCBhbmQgdGVhY2hlcnMgaGF2ZSBzaW1pbGFyIHBlcmNlcHRpb25zIGFib3V0IHRoZSBmb3VyIHNjaG9vbCBxdWFsaXR5IG1ldHJpY3MgdGhleSB3ZXJlIHN1cnZleWVkIGFib3V0OiAKCiAgICBTYWZldHkgYW5kIFJlc3BlY3QKICAgIENvbW11bmljYXRpb24KICAgIEVuZ2FnZW1lbnQKICAgIEFjYWRlbWljIEV4cGVjdGF0aW9ucwoKIFdlIGNhbiBncm91cCB0aGUgZGF0YSBieSBxdWVzdGlvbiBhbmQgc3VydmV5IHJlc3BvbnNlIHR5cGUgKHBhcmVudCwgc3R1ZGVudCwgdGVhY2hlciwgb3IgdG90YWwpIGFuZCB0aGVuIGNhbGN1bGF0ZSBhIHN1bW1hcnkgYXZlcmFnZSBmb3IgZWFjaCBncm91cC4KCmBgYHtyfQpjb21iaW5lZF9zdXJ2ZXlfZ2F0aGVyIDwtIGNvbWJpbmVkX2ZpbmFsICU+JQogIGdhdGhlcihrZXkgPSAic3VydmV5X3F1ZXN0aW9uIiwgdmFsdWUgPSAic2NvcmUiLCAxNzoyOCwzMykgJT4lCiAgbXV0YXRlKHJlc3BvbnNlX3R5cGUgPSBzdHJfc3BsaXQoYHN1cnZleV9xdWVzdGlvbmAsICJfIiwgc2ltcGxpZnkgPSBUUlVFKVssMl0sIG1ldHJpYyA9IHN0cl9zcGxpdChgc3VydmV5X3F1ZXN0aW9uYCwgIl8iLCBzaW1wbGlmeSA9IFRSVUUpWywxXSkgCiAgCmNvbWJpbmVkX3N1cnZleV9nYXRoZXIgPC0gY29tYmluZWRfc3VydmV5X2dhdGhlciAlPiUKICBtdXRhdGUocmVzcG9uc2VfdHlwZSA9IGlmX2Vsc2UocmVzcG9uc2VfdHlwZSA9PSAicCIsICJwYXJlbnQiLCBpZl9lbHNlKHJlc3BvbnNlX3R5cGUgPT0gInQiLCAidGVhY2hlciIsIGlmX2Vsc2UocmVzcG9uc2VfdHlwZSA9PSAicyIsICJzdHVkZW50IiwgInN0cF9jb21iaW5lZCIpKSkpCiAgCmBgYAojIyMjIE5vdyBpdHMgdGltZSB0byBncm91cCB0aGUgZGF0YSBpbnRvIGNhdGVnb3JpZXM6IFN0dWRlbnRzLCBUZWFjaGVycyBhbmQgUGFyZW50cy4gCgojIyMjIDEuIFN1bW1hcnkgcGVyY2VwdGlvbnM6IApgYGB7cn0KcGVyY2VwdGlvbnMgPC0gY29tYmluZWRfc3VydmV5X2dhdGhlciAlPiUKICBncm91cF9ieShyZXNwb25zZV90eXBlLCBtZXRyaWMpICU+JQogIHN1bW1hcml6ZShhdmdfc2NvcmUgPSBtZWFuKHNjb3JlLCBuYS5ybSA9IFRSVUUpKQpwZXJjZXB0aW9ucwpgYGAKYGBge3J9CmNvbWJpbmVkX3N1cnZleV9nYXRoZXIgPC0gY29tYmluZWRfc3VydmV5X2dhdGhlciAlPiUKICBkcm9wX25hKHNjb3JlKQoKYGBgCgpgYGB7cn0KY29tYmluZWRfc3VydmV5X2dhdGhlciAlPiUKICMgZmlsdGVyKHJlc3BvbnNlX3R5cGUgIT0gInF1YWxpdHkiKSAlPiUKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSBzdXJ2ZXlfcXVlc3Rpb24sIHkgPSBzY29yZSwgZmlsbCA9IHJlc3BvbnNlX3R5cGUpICsKICBnZW9tX2JveHBsb3QoKSArIAogIGxhYnModGl0bGUgPSAiUGVyY2VwdGlvbnMgb2YgcXVhbGl0eSBlZHVjYXRpb24gaW4gTllDIEhpZ2ggU2Nob29scyIpICsgCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEsIHNpemU9OCksIHBhbmVsLnNwYWNpbmcueD11bml0KDAuNSwgImxpbmVzIikpICAKCmBgYAoKIyMjIyBUaGVyZSBhcmUgc3RpbGwgaW50ZXJlc3RpbmcgcXVlc3Rpb25zIHdlIGNhbiBhbnN3ZXI6CgotIElzIHRoZXJlIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gZ2VuZGVyIHBlcmNlbnRhZ2VzIGFuZCBhdmVyYWdlIFNBVCBzY29yZXM/IEhvdyBhYm91dCBmb3IgdGhlIGRpZmZlcmVudCBzZWN0aW9ucyBvZiB0aGUgU0FUIChSZWFkaW5nLCBXcml0aW5nLCBhbmQgTWF0aCk/CgotIFdoaWNoIE5ZQyBzY2hvb2xzIHNlZW0gdG8gaGF2ZSB0aGUgYmVzdCBxdWFsaXR5IG1ldHJpY3MgYWNjb3JkaW5nIHRvIHN1cnZleSBkYXRhPyBJcyB0aGVyZSBhIGRpZmZlcmVuY2UgaWYgd2UgYnJlYWsgdGhpcyBkb3duIGJ5IHJlc3BvbnNlIHR5cGU/CgotIENhbiB3ZSBsZWFybiBhbnl0aGluZyBmcm9tIHRoZSBkaWZmZXJlbmNlcyBpbiBzY2hvb2wgcXVhbGl0eSBtZXRyaWMgcGVyY2VwdGlvbiBiZXR3ZWVuIGdyb3Vwcz8gRm9yIGV4YW1wbGUsIGlmIHdlIGNyZWF0ZWQgYSBuZXcgdmFyaWFibGUgYnkgc3VidHJhY3Rpbmcgc2FmX3BfMTEgZnJvbSBzYWZfcF8xMSwgY2FuIHRoaXMgZGlmZmVyZW5jZSBpbiBob3cgc3R1ZGVudHMgYW5kIHBhcmVudHMgcGVyY2VpdmUgc2FmZXR5IG1heSBiZSByZWxhdGVkIHRvIGFueSBvdGhlciB2YXJpYWJsZXM/CgoKCg==